package zsc.ruanc.practicaltraining.security.Filter;

import com.alibaba.druid.util.StringUtils;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.method.HandlerMethod;
import zsc.ruanc.practicaltraining.exception.ApiException;
import zsc.ruanc.practicaltraining.mapper.Redis;
import zsc.ruanc.practicaltraining.security.auth.AuthUser;
import zsc.ruanc.practicaltraining.security.exception.SAccessDeniedException;
import zsc.ruanc.practicaltraining.security.exception.SAuthenticationException;
import zsc.ruanc.practicaltraining.utils.TokenUtils;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Component
public class TokenFilter extends OncePerRequestFilter {

    @Autowired
    private Redis redis;

    @Autowired
    private UserDetailsService userDetailsService;


    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        System.out.println("----------------------------------------------");
        System.out.println("-----------token拦截器开始执行----------------------");
        System.out.println("----------------------------------------------");



        String requestURI = httpServletRequest.getRequestURI();
        AntPathMatcher antPathMatcher = new AntPathMatcher();

        System.out.println(requestURI);

        String[] list = new String[]{"/login", "/user/create", "/user/findPassword", "/test/**", "/user/getInfo",
                "/email/sendCode", "/email/sendFindPasswordCode",
                "/article/get/{id}", "/article/vagueQuery", "/article/userArticleList", "/article/recommend", "/article/selectCategories", "/article/getAllTrue",
                "/comment/commentPage", "/class/selectPage", "/class/getNameList", "/class/selectByName"};

        for (String item : list) {
            if (antPathMatcher.match(item, requestURI)) {
                filterChain.doFilter(httpServletRequest, response);
                return ;
            }
        }


        String token = httpServletRequest.getHeader("token");
        System.out.println(token);

        if (!StringUtils.isEmpty(token)) {

            int id = 0;
            try {
                Claim c = JWT.decode(token).getClaim("id");
                id = c.asInt();

            } catch (JWTDecodeException e) {
                throw new ApiException(-10, "请重新登录");


            } catch (IllegalArgumentException e) {

                throw new ApiException(-9, "无效的token");
            }

            String key = (String) redis.get(String.valueOf(id));
            if (key == null) {
                throw new ApiException(-9, "token被篡改");
            }

            JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(key)).build();
            DecodedJWT decodeJWT = null;
            try {
                decodeJWT = jwtVerifier.verify(token);
            } catch (JWTDecodeException e) {
                throw new ApiException(-9, "token被篡改");

            } catch (IllegalArgumentException e) {
                throw new SAuthenticationException("999999");

            }  catch (SignatureVerificationException e) {

                throw new ApiException(-9, "过期token");

            }

            String ip = httpServletRequest.getRemoteAddr();
            String role = decodeJWT.getClaim("role").asString();
            String name = decodeJWT.getSubject();
            System.out.println(name);
            System.out.println(ip);
            System.out.println(id);
            System.out.println(role);
//        httpServletRequest.setAttribute("ip", ip);
            httpServletRequest.setAttribute("id", id);
            httpServletRequest.setAttribute("name", name);
            // 用户的身份字符串
            httpServletRequest.setAttribute("role", role);


            AuthUser authUser = new AuthUser();
            List<SimpleGrantedAuthority> authorityList = new ArrayList<>();
            authorityList.add(new SimpleGrantedAuthority(role));
            authUser.setId(id);
            authUser.setUsername(name);
            authUser.setAuthorities(authorityList);

            UsernamePasswordAuthenticationToken authentication =
                    new UsernamePasswordAuthenticationToken(
                            authUser,
                            null,
                            authUser.getAuthorities()
                    );
            //
            authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest));
            // 将 authentication 存入 ThreadLocal，方便后续获取用户信息
            SecurityContextHolder.getContext().setAuthentication(authentication);


        }


        filterChain.doFilter(httpServletRequest, response);
    }
}
